package com.bone.modules.quartz.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bone.common.exception.BoneException;
import com.bone.common.util.BoneUtils;
import com.bone.modules.quartz.common.Constants;
import com.bone.modules.quartz.dto.QuartzAddOrUpdateDto;
import com.bone.modules.quartz.dto.QuartzShowDto;
import com.bone.modules.quartz.entity.QuartzJob;
import com.bone.modules.quartz.mapper.QuartzJobMapper;
import com.bone.modules.quartz.service.IQuartzJobService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bone.modules.quartz.util.QuartzUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 定时任务表 服务实现类
 *
 * @author 王可可
 * @since 2020-12-10
 */
@Service
@Slf4j
public class QuartzJobServiceImpl extends ServiceImpl<QuartzJobMapper, QuartzJob> implements IQuartzJobService {

    @Autowired
    private Scheduler scheduler;

    @Override
    public boolean addOrUpdateTask(QuartzAddOrUpdateDto quartzAddOrUpdateDto) {
        // 查找正在执行且Job为选择的Job时 直接返回
        List<QuartzJob> quartzJobList = baseMapper.selectList(new LambdaQueryWrapper<QuartzJob>()
                .eq(QuartzJob::getJobClassName, quartzAddOrUpdateDto.getJobClassName())
                .eq(QuartzJob::getStatus, Constants.STATUS_NORMAL));
        if (BoneUtils.listIsNotEmpty(quartzJobList)) {
            throw new BoneException("此类型任务正在执行，请先暂停同类型任务！");
        }
        QuartzJob quartzJob = quartzAddOrUpdateDto.buildEntity();

        // 判断id是否为空
        if (BoneUtils.isEmpty(quartzAddOrUpdateDto.getId())) {
            // 添加任务 - 判断Job已经存在 且 正在执行
            baseMapper.insert(quartzJob);
            log.info("添加定时任务成功>>>>>任务ID：" + quartzJob.getId());

        } else {
            // 更新任务 - 同理
            baseMapper.updateById(quartzJob);
            log.info("更新定时任务成功>>>>>任务ID：" + quartzJob.getId());
        }
        if (quartzAddOrUpdateDto.getStatus().equals(Constants.STATUS_NORMAL)) {
            // 判断是否直接执行
            QuartzUtil.schedulerAdd(
                    quartzAddOrUpdateDto.getJobClassName(),
                    quartzAddOrUpdateDto.getCronExpression(),
                    quartzAddOrUpdateDto.getParameter(),
                    scheduler);
        }
        return true;
    }

    @Override
    public List<QuartzShowDto> queryList() {
        return BoneUtils.entityListToModelList(baseMapper.selectList(null), QuartzShowDto.class);
    }


    @Override
    public void execute(QuartzJob quartzJob) throws Exception {
        String jobName = quartzJob.getJobClassName().trim();
        Date startDate = new Date();
        String ymd = DateUtil.now() + Math.random() * 100;
        // 唯一指标
        String identity = jobName + ymd;
        //3秒后执行 只执行一次
        startDate.setTime(startDate.getTime() + 3000L);
        // 定义一个Trigger
        SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger()
                .withIdentity(identity, Constants.JOB_TEST_GROUP)
                .startAt(startDate)
                .build();
        // 构建job信息
        JobDetail jobDetail = JobBuilder.newJob(QuartzUtil.getClass(jobName).getClass()).withIdentity(identity).usingJobData("parameter", quartzJob.getParameter()).build();
        // 将trigger和 jobDetail 加入这个调度
        scheduler.scheduleJob(jobDetail, trigger);
        // 启动scheduler
        scheduler.start();
    }

    @Override
    public void pause(String id) {
        QuartzJob quartzJob = baseMapper.selectById(id);
        if (quartzJob == null) {
            throw new BoneException("该任务不存在");
        }
        // 将这个Job从Scheduler调度器中移除
        QuartzUtil.schedulerDelete(quartzJob.getJobClassName().trim(), scheduler);
        quartzJob.setStatus(Constants.STATUS_DISABLE);
        // 更新数据库中的状态
        baseMapper.updateById(quartzJob);

        log.info("定时暂停————————Job路径:" + quartzJob.getJobClassName());
    }

    @Override
    public void resumeJob(String id) {
        QuartzJob quartzJob = baseMapper.selectById(id);
        if (quartzJob == null) {
            throw new BoneException("该任务不存在");
        }
        List<QuartzJob> quartzJobList = baseMapper.selectList(new LambdaQueryWrapper<QuartzJob>()
                .eq(QuartzJob::getJobClassName, quartzJob.getJobClassName())
                .eq(QuartzJob::getStatus, Constants.STATUS_NORMAL));
        if (BoneUtils.listIsNotEmpty(quartzJobList)) {
            throw new BoneException("此类型任务正在执行，请先暂停同类型任务！");
        }
        // 先将Job从Scheduler中移除
        QuartzUtil.schedulerDelete(quartzJob.getJobClassName().trim(), scheduler);
        // 再将Job重新添加进Scheduler中
        QuartzUtil.schedulerAdd(quartzJob.getJobClassName().trim(), quartzJob.getCronExpression().trim(), quartzJob.getParameter(), scheduler);
        // 修改Job的状态 0 代表正常启动
        quartzJob.setStatus(Constants.STATUS_NORMAL);
        // Job持久化
        baseMapper.updateById(quartzJob);

        log.info("定时启动————————Job路径:" + quartzJob.getJobClassName());
    }
}
